package io.renren.common.utils;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 程飞(家有喜娟儿)
 * @description 加解密工具类
 * @create 2020-10-10 6:55
 * @modify 2020-10-10 6:55
 * @e-mail chengtengfei35@163.com
 * @tel-ph 17331190952
 **/
public class JsencryptUtils {

    private static final Provider provider = new BouncyCastleProvider();

    private static final String PUBLIC_KEY = "RSAPublicKey";

    private static final String PRIVATE_KEY = "RSAPrivateKey";

    // 加密数据和秘钥的编码方式
    private static final String UTF_8 = "UTF-8";

    // 填充方式
    private static final String KEY_ALGORITHM = "RSA";


    // 初始化公钥 保存成常量或数据库纪录
    private static final String PUBLIC_KEY_STR = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n'" +
            "nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==";


    // 初始化私钥 保存成常量或数据库纪录
    private static final String PRIVATE_KEY_STR = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n'" +
            "'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n'" +
            "'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n'" +
            "'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n'" +
            "'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n'" +
            "'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n'" +
            "'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n'" +
            "'UP8iWi1Qw0Y=";


    /**
     * 生成密钥对(公钥和私钥)
     *
     * @return
     * @throws Exception
     */
    private static synchronized Map<String, Object> generateKeyPair() throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM, provider);
        kpg.initialize(1024, new SecureRandom());//seedKey.getBytes()
        KeyPair keyPair = kpg.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }


    /**
     * 获取公钥
     *
     * @param key base64加密后的公钥
     * @param key
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicRSAKey(String key) throws Exception {
        X509EncodedKeySpec x509 = new X509EncodedKeySpec(decryptBase64(key));
        KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM, provider);
        return kf.generatePublic(x509);
    }

    /**
     * 获取私钥
     *
     * @param key base64加密后的私钥
     * @param key
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateRSAKey(String key) throws Exception {
        PKCS8EncodedKeySpec pkgs8 = new PKCS8EncodedKeySpec(decryptBase64(key));
        KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM, provider);
        return kf.generatePrivate(pkgs8);
    }

    /**
     * base64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    private static byte[] decryptBase64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * base64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    private static String encryptBase64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }


    /**
     * 默认的RSA加密方法
     * 一般用来加密小数据参数
     *
     * @param publicKeyStr
     * @param data
     * @return
     */
    private static String encryptRSADefault(String publicKeyStr, String data) {
        KeyFactory keyFactory = null;
        try {
            keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        byte[] publicKeyArray = publicKeyStr.getBytes();
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyArray));
        PublicKey publicKey = null;
        try {
            publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        Cipher cipher = null;

        try {
            cipher = Cipher.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }

        try {
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

        try {
            byte[] re = cipher.doFinal(data.getBytes());
            return new String(Base64.encodeBase64(re), UTF_8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }

        return "";
    }


    /**
     * 默认的RSA加密方法
     * 一般用来解密小数据参数
     *
     * @param privateKeyStr
     * @param dataStr
     * @return
     */
    private static String decryptRSADefault(String privateKeyStr, String dataStr) {
        KeyFactory keyFactory = null;
        try {
            keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        byte[] privateKeyArray = privateKeyStr.getBytes();
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyArray));
        PrivateKey privateKey = null;
        try {
            privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        Cipher cipher = null;

        try {
            cipher = Cipher.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }

        try {
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

        try {
            return new String(cipher.doFinal(Base64.decodeBase64(dataStr.getBytes())), UTF_8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }

        return "";
    }

    /**
     * 默认的RSA加密方法(用于参数加密)
     *
     * @param data
     * @return
     */
    public static String encryptRSADefault(String data) {
        return encryptRSADefault(PUBLIC_KEY_STR, data);
    }


    /**
     * 默认的RSA解密方法(用于参数解密)
     *
     * @param data
     * @return
     */
    public static String decryptRSADefault(String data) {
        return decryptRSADefault(PRIVATE_KEY_STR, data);
    }

    /**
     * 主测试方法
     *
     * @param args
     */
    public static void main(String args[]) {
        String admin123 = encryptRSADefault("039325");
        System.out.println(admin123);

        String s = decryptRSADefault(admin123);
        System.out.println(s);
    }
}
